By
yusijia
June 28 2016
Updated:June 28 2016
参考:《改善java程序的151个建议》http://blog.csdn.net/chenssy/article/details/44102915
我们知道subList生成的子列表只是原列表的一个视图而已,如果我们操作子列表它产生的作用都会在原列表上面表现,但是如果我们操作原列表会产生什么情况呢?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 1. public static void main(String[] args) { 2. List<Integer> list1 = new ArrayList<Integer>(); 3. list1.add(1); 4. list1.add(2); 5. 6. //通过subList生成一个与list1一样的列表 list3 7. List<Integer> list3 = list1.subList(0, list1.size()); 8. //修改list3 9. list1.add(3); 10. 11. System.out.println("list1'size:" + list1.size()); 12. System.out.println("list3'size:" + list3.size()); 13. } 输出: 1. list1'size:3 2. Exception in thread "main" java.util.ConcurrentModificationException 3. at java.util.ArrayList$SubList.checkForComodification(Unknown Source) 4. at java.util.ArrayList$SubList.size(Unknown Source) 5. at com.chenssy.test.arrayList.SubListTest.main(SubListTest.java:17)
subList的size方法出现了异常,而且还是并发修改异常。。。。。。这里没有使用多线程操作,何来的并发修改呢?
我们在来看看subList的size方法:
1 2 3 4 5 6 7 8 9 10 1 . public int size () { 2 . checkForComodification(); 3 . return this .size; 4 . } size方法首先会通过checkForComodification验证,然后再返回this .size。该方法就是用于检测是否并发修改的。 1 . private void checkForComodification () { 2 . 3 . if (ArrayList.this .modCount != this .modCount) 4 . throw new ConcurrentModificationException(); 5 . }
该方法表明当原列表的modCount与this.modCount不相等时就会抛出ConcurrentModificationException。同时我们知道modCount 在new的过程中 “继承”了原列表modCount,只有在修改该列表(子列表)时才会修改该值(先表现在原列表后作用于子列表)。而在该实例中我们是操作原列表,原列表的modCount当然不会反应在子列表的modCount上啦,所以才会抛出该异常。
subList的其他方法也会检测修改计数器,若生成子列表后再直接修改了原列表,这些方法会抛出ConcurrentModificationException 异常。
对于子列表视图,它是动态生成的,生成之后就不要操作原列表了,否则必然都导致视图的不稳定而抛出异常。最好的办法就是将原列表设置为只读状态,要操作就操作子列表:
1 2 3 4 1 . List<Integer> list3 = list1.subList(0 , 1 ); 2 . 3 . 4 . list1 = Collections.unmodifiableList(list1);
还有个问题: List可以生成多个子列表,但问题是只要生成的子列表多于一个,则任何一个子列表都不能修改了否则抛出并发修改异常。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 public static void main (String[] args) { List<String> c = new ArrayList<String>(); c.add("A" ); c.add("B" ); c.add("C" ); List<String> c1 = c.subList(0 , 2 ); c = Collections.unmodifiableList(c); System.out.println(c1); List<String> c2 = c.subList(1 , 3 ); System.out.println(c2); c2.add("D" ); System.out.println(c2); }